/// @tags: NTT Polynomial
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>

typedef long long ll;
int const N = 1 << 18, P = 998244353, G = 3, iG = 332748118;

template <typename T>
inline T &read(T &x) {
  x = 0;
  bool f = false;
  short ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = true;
    ch = getchar();
  }
  while (isdigit(ch)) x = x * 10 + (ch ^ '0'), ch = getchar();
  if (f) x = -x;
  return x;
}

class Polynomial {
 private:
  int f[N];
  static int Cvt[N << 2];

 public:
  int maxl;
  void NTT(const bool typ, const int n);
  int &operator[](int index) { return f[index]; };
  int const &operator[](int index) const { return f[index]; };
  inline static void pre(int n) {
    for (int i = 1, len = 2; len <= n; ++i, len <<= 1)
      for (int j = 1, *const cvt = Cvt + len - 1; j < len; ++j)
        cvt[j] = cvt[j >> 1] >> 1 | ((j & 1) << (i - 1));
  }
  inline void clear(int n) {
    maxl = 1;
    while (maxl < n) maxl <<= 1;
    memset(f, 0, sizeof(int) * maxl);
  }
} f, g;

int n, ans;
int Polynomial::Cvt[N << 2], fac[N], ifac[N];

inline ll qpow(ll base, int exp) {
  ll res = 1;
  while (exp) {
    if (exp & 1) res = res * base % P;
    base = base * base % P;
    exp >>= 1;
  }
  return res;
}

inline void Polynomial::NTT(bool const typ, int const n) {
  for (int i = 1, *const cvt = Cvt + n - 1; i < n; ++i)
    if (i < cvt[i]) std::swap(f[i], f[cvt[i]]);
  for (int i = 2; i <= n; i <<= 1) {
    int mid = i >> 1, wn = qpow(typ ? G : iG, (P - 1) / i);
    for (int j = 0; j < n; j += i) {
      ll wk = 1;
      for (int k = 0; k < mid; ++k, (wk *= wn) %= P) {
        ll t = wk * f[j + k + mid] % P;
        if ((f[j + k + mid] = f[j + k] - t) < 0) f[j + k + mid] += P;
        if ((f[j + k] += t) >= P) f[j + k] -= P;
      }
    }
  }
  if (!typ) {
    ll inv = qpow(n, P - 2);
    for (int i = 0; i < n; ++i) f[i] = inv * f[i] % P;
  }
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("P4091 [HEOI2016]求和.in", "r", stdin);
  freopen("P4091 [HEOI2016]求和.out", "w", stdout);
#endif
#endif

  read(n);
  f.clear(n + 1);
  f[0] = g[0] = 1, f[1] = P - 1, g[1] = n + 1;
  fac[0] = 1;
  for (int i = 1; i <= n; ++i) fac[i] = 1ll * fac[i - 1] * i % P;
  ifac[n] = qpow(fac[n], P - 2);
  for (int i = n - 1; ~i; --i) ifac[i] = 1ll * ifac[i + 1] * (i + 1) % P;
  for (int i = 2; i <= n; ++i)
    f[i] = i & 1 ? P - ifac[i] : ifac[i],
    g[i] = (qpow(i, n + 1) - 1) * qpow(i - 1, P - 2) % P * ifac[i] % P;
  f.maxl <<= 1;
  Polynomial::pre(f.maxl);
  f.NTT(true, f.maxl), g.NTT(true, f.maxl);
  for (int i = 0; i < f.maxl; ++i) f[i] = 1ll * f[i] * g[i] % P;
  f.NTT(false, f.maxl);
  for (int i = 0; i <= n; ++i)
    if ((ans += qpow(2, i) * fac[i] % P * f[i] % P) >= P) ans -= P;
  printf("%d", ans);
  return 0;
}